package com.ecarx.common

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import java.lang.reflect.ParameterizedType

abstract  class BaseFragment<V : ViewModel,T : ViewDataBinding> : Fragment() {
    protected var mActivity: AppCompatActivity? = null
    protected val DEFAULT_VARIABLE = -1
    open var mViewModel: V? = null
    protected var binding: T? =null
    protected var mSharedViewModel: SharedViewModel? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mSharedViewModel = getAppViewModelProvider()?.get(SharedViewModel::class.java)
        mViewModel = initViewModel()
    }
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(LayoutInflater.from(context),getLayoutResId(),container,false)
        binding?.lifecycleOwner = this
        val viewModelId = getViewModelId()
        if (viewModelId != DEFAULT_VARIABLE) {
            binding?.setVariable(viewModelId, mViewModel)
        }
        initView(binding?.root)
        return binding?.root

    }


    override fun onAttach(context: Context) {
        super.onAttach(context)
        mActivity = context as AppCompatActivity
    }

      open fun initViewModel(): V? {
        return getViewModel()!!
    }

    private  fun getViewModel(): V? {
        var clazz: Class<*>? = this.javaClass
        var classViewModel: Class<*>? = null
        while (clazz != null && clazz.genericSuperclass != null) {
            if (clazz.genericSuperclass is ParameterizedType) {
                classViewModel =
                    (clazz.genericSuperclass as ParameterizedType?)!!.actualTypeArguments[0] as Class<*>
                if (ViewModel::class.java.isAssignableFrom(classViewModel!!) && BaseFragment::class.java == clazz.superclass) {
                    break
                }
            }
            clazz = clazz.superclass
        }
        if (classViewModel == null) {
            return null
        }

            val viewModelProvider = ViewModelProvider(
                getViewModelStoreOwner(),
                ViewModelProvider.AndroidViewModelFactory.getInstance(mActivity?.getApplication()!!)
            )
          return viewModelProvider.get(classViewModel as Class<ViewModel>) as V
    }

     fun getViewModelStoreOwner(): ViewModelStoreOwner {
        return this
    }

    protected abstract fun getViewModelId(): Int

    @LayoutRes
    protected abstract fun getLayoutResId(): Int

    protected abstract fun initView(view: View?)

    private  fun getAppViewModelProvider(): ViewModelProvider? {
        return (mActivity!!.applicationContext as BaseApplication).getAppViewModelProvider()
    }

}